package org.webscale.json.client;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.UUID;
import java.util.concurrent.Callable;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.log4j.Logger;
import org.webscale.json.JSONServlet;
import org.webscale.json.client.JsonClient.ResultNotifier;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class JsonClient<V> implements Callable<V> {
	private static final Logger log = Logger.getLogger(JsonClient.class);
	private String submissionURL;
	private String jsonRequestId;
	private Object objTosubmit;
	private Type objSubmitType;
	private Class<V> responseClazz;
	private String uuid;
	private ResultNotifier notifier;
	
	public JsonClient() {
		super();
	}
	
	public JsonClient(String url, String id, Object obj) {
		this();
		this.submissionURL = url;
		this.jsonRequestId = id;
		this.objTosubmit = obj;
		uuid = UUID.randomUUID().toString();
	}
	

	public V call() throws Exception {
		String response = "";
		response = executeJSONPost();
		Gson gson = new Gson();
		log.info("response Class= " + responseClazz);
		V responseObject = (V) gson.fromJson(response, responseClazz);
		return responseObject;
	}
	
	public String getUuid() {
		return uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	
	
	protected String getJSONRequestString() {
		Gson gson = new Gson();
	//	String json = gson.toJson(this.getObjTosubmit());
		
	  //  Type listType = new TypeToken() {}.getType();
		String json  = gson.toJson(getObjTosubmit() , objSubmitType);
		return json;

	}

	

	public Type getObjSubmitType() {
		return objSubmitType;
	}

	public void setObjSubmitType(Type objSubmitType) {
		this.objSubmitType = objSubmitType;
	}

	public ResultNotifier getNotifier() {
		return notifier;
	}

	public void setNotifier(ResultNotifier notifier) {
		this.notifier = notifier;
	}

	public String executeJSONPost() throws HttpException, IOException {
		HttpClient client = new HttpClient();
		PostMethod postMethod = new PostMethod(submissionURL);

		NameValuePair requestID = new NameValuePair(JSONServlet.REQUEST_ID,
				jsonRequestId);
		NameValuePair requestString = new NameValuePair(
				JSONServlet.JSON_REQUEST_STRING, getJSONRequestString());

		postMethod.setRequestBody(new NameValuePair[] { requestID,
				requestString });
		client.executeMethod(postMethod);
		String response = postMethod.getResponseBodyAsString();
		log.info("response - " + response);
		return response;
	}

	public String getJsonRequestId() {
		return jsonRequestId;
	}

	public void setJsonRequestId(String jsonRequestId) {
		this.jsonRequestId = jsonRequestId;
	}

	public String getSubmissionURL() {
		return submissionURL;
	}

	public void setSubmissionURL(String submissionURL) {
		this.submissionURL = submissionURL;
	}

	public Object getObjTosubmit() {
		return objTosubmit;
	}

	public void setObjTosubmit(Object objTosubmit) {
		this.objTosubmit = objTosubmit;
		objSubmitType = objTosubmit.getClass();
	}

	public Class<V> getResponseClazz() {
		return responseClazz;
	}

	public void setResponseClazz(Class<V> responseClazz) {
		this.responseClazz = responseClazz;
	}
	
	public interface ResultNotifier<V> {
		public void onComplete(V response);
	}

}
